/**
 * @author phi
 * canvas を拡張
 */

(function(){ "use strict"; })();
(function(){
    var DOM = TM.DOM = TM.DOM || {}
})();


// dom をロード
TM.loadScript("dom", "dom", function(){

/**
 * context の拡張
 */
(function(){
    
    // #pragma 的なものだと思ってもらえれば...
    if (!TM.DOM.Element) {
        setTimeout(arguments.callee, 0); return ;
    }
    
    var Canvas = TM.DOM.Canvas = TM.createClass({
        superClass: TM.DOM.Element,
        
        context: null,
        
        init: function(target) {
            // デフォルト値設定
            target = target || TM.$create("canvas");
            // 親の初期化
            TM.DOM.Element.prototype.init.apply(this, arguments);
            // canvas かをチェック
            console.assert(this.element instanceof HTMLCanvasElement);
            // コンテキストを取得
            this.context = this.element.getContext('2d');
        },
        
        fullScreen: function() {
            this.element.style.position = "fixed";
            this.element.style.margin= "0";
            this.element.style.padding = "0";
            this.element.style.left = "0px";
            this.element.style.top  = "0px";
            this.element.width = window.innerWidth;
            this.element.height = window.innerHeight;
            
            var self = this;
            window.addEventListener("resize", function(){
                self.element.width = window.innerWidth;
                self.element.height = window.innerHeight;
            });
        },
    });
    
    Canvas.prototype.accessor("width", {
        "get": function()   { return this.element.width; },
        "set": function(v)  { this.element.width = v;    }
    });
    
    Canvas.prototype.accessor("height", {
        "get": function()   { return this.element.height; },
        "set": function(v)  { this.element.height = v;    }
    });
    
})();

/*
 * imageData
 */
(function(){
    
    var Canvas = TM.DOM.Canvas;

    var ImageData = TM.createClass({
        
        dom: null,
        imageData: null,
        
        init: function(dom) {
            this.dom = dom;
            this.imageData = null;
        },
        
        setup: function(x, y, width, height) {
            this.imageData = this.dom.context.getImageData(x, y, width, height);
        },
        
                    
        getPixel: function(index) {
            var i = index*4;
            return [
                this.imageData.data[i+0],
                this.imageData.data[i+1],
                this.imageData.data[i+2],
                this.imageData.data[i+3]
            ];
        },
        
        setPixel: function(index, pixel)
        {
            // アルファ
            pixel[3] = pixel[3] || 255;
            var i = index*4;
            this.imageData.data[i+0] = pixel[0];
            this.imageData.data[i+1] = pixel[1];
            this.imageData.data[i+2] = pixel[2];
            this.imageData.data[i+3] = pixel[3];
            
            return this;
        },
        
        filter: function(fn)
        {
            for (var i=0; i<this.length; ++i)
            {
                var p = this.getPixel(i);
                p = fn(p);
                this.setPixel(i, p);
            }
            
            return this;
        }
        
    });
    
    /*
    temp.prototype.accessor("width", {
        "get": function()   { return this.target.width; },
        "set": function(v)  { this.target.width = v;    }
    });

    
    temp.prototype.accessor("height", {
        "get": function()   { return this.target.height; },
        "set": function(v)  { this.target.height = v;    }
    });
    
    temp.prototype.__defineGetter__("length", function(){
        return this.target.width*this.target.height;
    });
    */
    
    Canvas.prototype.getter("imageData", function(){
        return this._imageData || ( this._imageData = ImageData(this) );
    });
    
})();


/*
 * filter
 */
(function(){
    
    var Canvas = TM.DOM.Canvas;

    var Filter = TM.createClass({
        
        dom: null,
        
        init: function(dom) {
            this.dom = dom;
        },
        
        filter: function(fn, x, y, width, height)
        {
            x       = x || 0;
            y       = y || 0;
            width   = width || this.dom.element.width;
            height  = height|| this.dom.element.height;
            
            var imageData = this.dom.imageData;
            imageData.setup(x, y, width, height);
            
            for (var i=0; i<width; ++i) {
                for (var j=0; j<height; ++j) {
                    var index = j*width + i;
                    var p = imageData.getPixel(index);
                    p = fn(p);
                    imageData.setPixel(index, p);
                }
            }
            
            this.dom.context.putImageData(imageData.imageData, x, y);
        },
        
        reverse: function(x, y, width, height)
        {
            this.filter(function(p){
                p[0] = 255-p[0];
                p[1] = 255-p[1];
                p[2] = 255-p[2];
                
                return p;
            }, x, y, width, height);
        },
        
        monochrome: function(x, y, width, height)
        {
            this.filter(function(p){
                var grayscale = p[0]*0.3 + p[1]*0.59 + p[2]*0.11;
                p[0] = grayscale;
                p[1] = grayscale;
                p[2] = grayscale;
                
                return p;
            }, x, y, width, height);
        },
        
        red: function(x, y, width, height)
        {
            this.filter(function(p){
                p[0]=p[0]*2;
                if (p[0] > 255) p[0] = 255;
                p[1] = Math.floor(p[1]/2);
                p[2] = Math.floor(p[2]/2);
                
                return p;
            }, x, y, width, height);
        },
        
    });
    
    
    Canvas.prototype.getter("filter", function(){
        return this._filter || ( this._filter = Filter(this) );
    });
    
})();



    
});

